package com.qipay.admin.filter;

import com.google.gson.Gson;
import com.qipay.baas.model.OperateLog;
import com.qipay.baas.model.User;
import com.qipay.operate.service.OperateLogService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.Arrays;
import java.util.Date;
import java.util.Map;

/**
 * Creator: Yao
 * Date:    2017/10/12
 * For:
 * Other:
 */
@Component
public class LogFilter implements Filter {

    private static Logger logger = LoggerFactory.getLogger(LogFilter.class);

    @Autowired
    OperateLogService logService;

    private final String service = "admin";

    private static Gson gson;
    private String[] methods = {"POST", "PUT", "DELETE"};
    private String[] managerGetUrls = {};

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        if (null == gson)
            gson = new Gson();
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

        // init
        HttpServletRequest req = (HttpServletRequest) request;
        OperateLog log = null;

        // check
        String method = req.getMethod();
        String url = req.getRequestURL().toString();
        if (filter(method, url)) {

            log = new OperateLog();
            log.setService(service);
            log.setOperateDate(new Date());

            // ip
            String ip = req.getHeader("X-Real-IP");
            log.setIp(StringUtils.isBlank(ip) ? req.getRemoteHost() : ip);

            // user
            HttpSession session = req.getSession();
            Object user = session.getAttribute("user");
            if (null == user)
                log.setUserId(null);
            else if (user instanceof User) {
                log.setUserId(((User) user).getId());
            }
            log.setUrl(req.getServletPath());
            log.setMethod(method);

            // param
            Map<String, String[]> map = req.getParameterMap();
            if (null != map && map.size() > 0) {
                String param = gson.toJson(map);
                param = param.length() > 255 ? param.substring(0, 255) : param;
                log.setParam(param);
            }

            // info
            log.setInfo(convert2Info(url, method, map));

            logger.info(gson.toJson(log));
            try {
                logService.save(log);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        chain.doFilter(request, response);
    }

    /**
     * 过滤需要进行记录的信息
     *
     * @param method
     * @param url
     * @return
     */
    private boolean filter(String method, String url) {

        // commons
        if (StringUtils.isBlank(method))
            return false;
        if (Arrays.asList(methods).contains(method.toUpperCase()))
            return true;

        // special
        if ("GET".equalsIgnoreCase(method)
                && managerGetUrls.length > 0
                && Arrays.asList(managerGetUrls).stream().anyMatch(p -> url.indexOf(p) > -1))
            return true;

        return false;
    }

    /**
     * 转换为描述信息
     *
     * @param url    请求完整地址
     * @param method 请求方式
     * @param map    请求参数
     * @return
     */
    private String convert2Info(String url, String method, Map<String, String[]> map) {

        String info = null;
        String pattern = "";
        String methodName = methodInfo(method);

        pattern = "/login/pass";
        if (url.contains(pattern)) return "登录成功";
        pattern = "/sys/changepwd-save";
        if (url.contains(pattern)) return "更改密码";

        pattern = ".*/withdraw.*";
        if (url.matches(pattern)) {
            if (url.contains("/cancel")) return "取消提现申请";
            else if (url.contains("/pass")) return "审批通过提现申请";
            else return "提现申请";
        }
        pattern = ".*/sp/.*";
        if (url.matches(pattern)) {
            if (url.contains("/sp/save")) return String.format("%s SP", methodName);
            else if (url.contains("/sp/api/save")) return String.format("%s SP 配置", methodName);
            else if (url.contains("/sp/channel/save")) return String.format("%s SP 渠道", methodName);
        }
        pattern = ".*/order/.*";
        if (url.matches(pattern)) {
            if (url.contains("/freeze")) return "冻结订单";
            else if (url.contains("/unfreeze")) return "取消订单冻结";
        }
        pattern = ".*/cp/.*";
        if (url.matches(pattern)) {
            if (url.contains("/cp/save")) return String.format("%s CP", methodName);
            else if (url.contains("/cp/channel/save")) return String.format("%s CP 渠道", methodName);


        }

        pattern = ".*/proxy/.*";
        if (url.matches(pattern)) {
            if (url.contains("/proxy/save")) return String.format("%s CP", methodName);
            else if (url.contains("/proxy/channel/save")) return String.format("%s CP 渠道", methodName);
        }

        pattern = ".*/doc/.*";
        if (url.matches(pattern)) {
            if (url.contains("/doc/save")) return String.format("%s文档目录", methodName);
            else if (url.contains("/doc/child/save")) return String.format("%s文档", methodName);
        }

        pattern = ".*/sp/.*";
        if (url.matches(pattern)) {
            if (url.contains("/sp/ronghuimch/save")) return String.format("%s 融汇入网商户", methodName);
            if (url.contains("/sp/ronghuimch/paytype/save")) return String.format("%s 融汇sp支付类型", methodName);
            if (url.contains("/sp/ronghuimch/")) return String.format("%s 融汇sp 进网", methodName);

        }

        return info;
    }

    /**
     * 操作方式名称转换
     *
     * @param method
     * @return
     */
    private String methodInfo(String method) {
        switch (method.toUpperCase()) {
            case "PUT":
                return "修改";
            case "POST":
                return "新增";
            case "DELETE":
                return "删除";
            default:
                return method;
        }
    }

    @Override
    public void destroy() {
    }
}
